/*
 * Copyright (C) 2008 GeoScheduler team, as stated on <http://www.geoscheduler.org/authors>.
 * 
 * This file is part of GeoScheduler.
 * 
 * GeoScheduler is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * GeoScheduler is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with GeoScheduler. If not, see <http://www.gnu.org/licenses/>.
 */
package org.geoscheduler.android.activities;

import java.util.List;

import org.geoscheduler.android.R;
import org.geoscheduler.android.maps.MapOverviewOverlay;
import org.geoscheduler.android.tools.DBHelper;
import org.geoscheduler.model.Event;

import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.sqlite.SQLiteDatabase;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.os.Bundle;
import android.view.View;
import android.widget.CheckBox;
import android.widget.ImageButton;
import android.widget.Toast;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;

/**
 * Map overview from current user's view 
 * 
 * @author paja
 */
public class MapOverview extends MapActivity {

	private static final int MINIMUM_TIME_BETWEEN_UPDATE = 5;
	
	private static final int MINIMUM_DISTANCECHANGE_FOR_UPDATE = 50;
	
	public static final String EXTRA_MAP_SELECT_MODE = "org.geoscheduler.android.maps.map.select";
	
	public enum ViewType {
		OVERVIEW, SELECTION;
	}

	protected ViewType currentState = ViewType.OVERVIEW;

	protected GeoPoint sourceLocation;

	/* UI and controlling stuff */
	protected LocationManager locationManager;
	protected GeoPoint location;
	protected MapView mapView;
	protected MapController mapController;
	protected MapOverviewOverlay moOverlay;
	protected LocationProvider provider;

	protected CheckBox cbWatchMe;
	
	protected ImageButton btnSearch;
	
	protected ImageButton btnSelect;

	/* Location change intent stuff */
	protected static final String LOCATION_CHANGED_ACTION = new String(
		"org.geoscheduler.android.intent.action.LOCATION_CHANGED");
	protected final IntentFilter locChgFilter = new IntentFilter(
		LOCATION_CHANGED_ACTION);
	protected final LocationListener locList = new LocListener(this);

	@SuppressWarnings("unchecked")
	private void updateView(boolean centerMap) {
		
		if (currentState == ViewType.OVERVIEW) {
			SQLiteDatabase db = DBHelper.openDB(this);
			moOverlay.events = (List) DBHelper.fetchAllInsts(db, new Event());
			db.close();
		}
		
		if (provider != null) {
			Location tmpLoc = locationManager.getLastKnownLocation(provider.getName());
			if (tmpLoc != null) {
				Double lat = tmpLoc.getLatitude() * 1E6;
				Double lng = tmpLoc.getLongitude() * 1E6;
				GeoPoint tmpLocation = new GeoPoint(lat.intValue(), lng.intValue());
				if (sourceLocation != null) {
					location = sourceLocation;
					sourceLocation = null;
				} else {
					location = tmpLocation;
				}
				moOverlay.currentLocation = tmpLocation;
				if (centerMap) {
					mapController.setCenter(location);				
				}
				mapView.invalidate();
			} else {
				Toast.makeText(this.getApplicationContext(), R.string.ee_msg_location_null, 10000);
			}
		}
	}

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle icicle) {
		super.onCreate(icicle);

		initActivity();
		initView();
		setListeners();
		updateView(true);
	}

	protected void initActivity() {
		currentState = ViewType.OVERVIEW;
		
		sourceLocation = null;
		
		Intent intent = getIntent();
		if (intent.hasExtra(EXTRA_MAP_SELECT_MODE)) {
			currentState = ViewType.SELECTION;
			
			if (intent.hasExtra(EditEvent.LOCATION_LAT)
					&& intent.hasExtra(EditEvent.LOCATION_LON)) {
				int tmpLat = intent.getIntExtra(EditEvent.LOCATION_LAT, 0);
				int tmpLon = intent.getIntExtra(EditEvent.LOCATION_LON, 0);
				
				sourceLocation = new GeoPoint(tmpLat, tmpLon);
			}			
		}
	}
	
	protected void initView() {
		setContentView(R.layout.map_overview);
		
		cbWatchMe = (CheckBox) findViewById(R.id.mo_watch_me);
		cbWatchMe.setChecked(false);

		btnSearch = (ImageButton) findViewById(R.id.mo_search_button);
		btnSelect = (ImageButton) findViewById(R.id.mo_select_button);

		mapView = (MapView) findViewById(R.id.mo_map);		
		mapController = mapView.getController();
		mapController.setZoom(18);

		// FIXME check please
		List<Overlay> overlays = mapView.getOverlays();
		moOverlay = new MapOverviewOverlay(this);
		overlays.add(moOverlay);
		mapView.postInvalidate();
		
		locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
		provider = locationManager.getProvider(EditEvent.FIXED_LOCATION_PROVIDER);	

		if (currentState == ViewType.OVERVIEW) {
			setTitle(getString(R.string.mo_title));
			btnSelect.setVisibility(View.INVISIBLE);
		} else
		if (currentState == ViewType.SELECTION) {
			setTitle(getString(R.string.mo_events_select));
			btnSelect.setVisibility(View.VISIBLE);
		}
	}
	
	/**
	 * Takes care of setting up all ListEvents listeners
	 */
	protected void setListeners() {

		/* New button click listener */
		btnSelect.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View arg0) {
				Intent data = new Intent();
				GeoPoint selectedLoc = mapView.getMapCenter();				
				data.putExtra(EditEvent.LOCATION_LAT, selectedLoc.getLatitudeE6());
				data.putExtra(EditEvent.LOCATION_LON, selectedLoc.getLongitudeE6());
				
				setResult(RESULT_OK, data);				
				finish();				
			}
		});

		btnSearch.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View arg0) {
				
				Toast.makeText(MapOverview.this, R.string.msg_not_implemented, Toast.LENGTH_SHORT).show();
			}
		});		
	}

	@Override
	public void onPause() {
		if (provider != null) {
			locationManager.removeUpdates(locList);
		}
		super.onPause();
	}

	@Override
	public void onResume() {
		super.onResume();
		if (provider != null) {			
			locationManager.requestLocationUpdates(provider.getName(),
					MINIMUM_TIME_BETWEEN_UPDATE,
					MINIMUM_DISTANCECHANGE_FOR_UPDATE, 
					locList);
		}
	}
	
	static class LocListener implements LocationListener {
		MapOverview relatedContext;
	
		public LocListener(MapOverview relatedContext) {
			super();
			this.relatedContext = relatedContext;
		}

		/**
		 * @see android.location.LocationListener#onLocationChanged(android.location.Location)
		 */
		@Override
		public void onLocationChanged(Location location) {
			if (relatedContext != null) {
				relatedContext.updateView(relatedContext.cbWatchMe.isChecked());
			}
		}

		// FIXME do we need to react to these?
		
		/**
		 * @see android.location.LocationListener#onProviderDisabled(java.lang.String)
		 */
		@Override
		public void onProviderDisabled(String provider) {
			// TODO Auto-generated method stub
		}

		/**
		 * @see android.location.LocationListener#onProviderEnabled(java.lang.String)
		 */
		@Override
		public void onProviderEnabled(String provider) {
			// TODO Auto-generated method stub
		}

		/**
		 * @see android.location.LocationListener#onStatusChanged(java.lang.String, int, android.os.Bundle)
		 */
		@Override
		public void onStatusChanged(String provider, int status, Bundle extras) {
			// TODO Auto-generated method stub
		}
		
	}

	/**
	 * @see com.google.android.maps.MapActivity#isRouteDisplayed()
	 */
	@Override
	protected boolean isRouteDisplayed() {
		return false;
	}
}
